package com.dean.test.csv;

import javax.tools.*;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URLClassLoader;
import java.util.Arrays;

public class DynamicCompilationExample {
    public static void main(String[] args) throws Exception {
        // 1. 创建一个 JavaCompiler 对象
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

        // 2. 创建一个 DiagnosticCollector 对象，用于收集编译时的诊断信息
        DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();

        // 3. 创建一个 StandardJavaFileManager 对象用于管理源文件和类文件
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);

        // 4. 创建一个动态内存中的 Java 源文件对象
        String sourceCode = "public class HelloWorld { public static void main(String[] args) { System.out.println(\"Hello, world\"); } }";
        JavaFileObject sourceFile = new DynamicJavaSourceCodeObject("HelloWorld", sourceCode);

        // 5. 配置编译选项
        Iterable<String> options = null;
        Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(sourceFile);

        // 6. 调用 JavaCompiler 的 getTask 方法获取一个 CompilationTask 对象
        JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits);

        // 7. 执行任务并检查返回值
        boolean success = task.call();
        if (!success) {
            for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
                System.out.format("Error on line %d in %s%n",
                        diagnostic.getLineNumber(),
                        diagnostic.getSource().toUri());
            }
            return;
        }

        // 8. 加载并执行编译后的类
        ClassLoader classLoader = DynamicCompilationExample.class.getClassLoader();
       // Class<?> clazz = Class.forName("HelloWorld");
        Class<?> clazz = classLoader.loadClass("HelloWorld");

        Object instance = clazz.newInstance();
        Method method = clazz.getMethod("main", String[].class);
        String[] arguments = new String[0];
        method.invoke(instance, (Object) arguments);

        fileManager.close();
    }

    /**
     * 动态内存中的 Java 源文件对象
     */
    static class DynamicJavaSourceCodeObject extends SimpleJavaFileObject {
        private final String code;

        public DynamicJavaSourceCodeObject(String name, String code) {
            super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
            this.code = code;
        }

        @Override
        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
            return code;
        }
    }
}
